Regular expression to match numbers with or without commas and decimals in text 您所在的位置:网站首页 pandas strmatch Regular expression to match numbers with or without commas and decimals in text

Regular expression to match numbers with or without commas and decimals in text

2023-04-07 22:37| 来源: 网络整理| 查看: 265

The regex below will match both numbers from your example.

\b\d[\d,.]*\b

It will return 5000 and 99,999.99998713 - matching your requirements.

EDIT: Since this has gotten a lot of views, let me start by giving everybody what they Googled for: #ALL THESE REQUIRE THE WHOLE STRING TO BE A NUMBER #For numbers embedded in sentences, see discussion below #### NUMBERS AND DECIMALS ONLY #### #No commas allowed #Pass: (1000.0), (001), (.001) #Fail: (1,000.0) ^\d*\.?\d+$ #No commas allowed #Can't start with "." #Pass: (0.01) #Fail: (.01) ^(\d+\.)?\d+$ #### CURRENCY #### #No commas allowed #"$" optional #Can't start with "." #Either 0 or 2 decimal digits #Pass: ($1000), (1.00), ($0.11) #Fail: ($1.0), (1.), ($1.000), ($.11) ^\$?\d+(\.\d{2})?$ #### COMMA-GROUPED #### #Commas required between powers of 1,000 #Can't start with "." #Pass: (1,000,000), (0.001) #Fail: (1000000), (1,00,00,00), (.001) ^\d{1,3}(,\d{3})*(\.\d+)?$ #Commas required #Cannot be empty #Pass: (1,000.100), (.001) #Fail: (1000), () ^(?=.)(\d{1,3}(,\d{3})*)?(\.\d+)?$ #Commas optional as long as they're consistent #Can't start with "." #Pass: (1,000,000), (1000000) #Fail: (10000,000), (1,00,00) ^(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$ #### LEADING AND TRAILING ZEROES #### #No commas allowed #Can't start with "." #No leading zeroes in integer part #Pass: (1.00), (0.00) #Fail: (001) ^([1-9]\d*|0)(\.\d+)?$ #No commas allowed #Can't start with "." #No trailing zeroes in decimal part #Pass: (1), (0.1) #Fail: (1.00), (0.1000) ^\d+(\.\d*[1-9])?$

Now that that's out of the way, most of the following is meant as commentary on how complex regex can get if you try to be clever with it, and why you should seek alternatives. Read at your own risk.

This is a very common task, but all the answers I see here so far will accept inputs that don't match your number format, such as ,111, 9,9,9, or even .,,.. That's simple enough to fix, even if the numbers are embedded in other text. IMHO anything that fails to pull 1,234.56 and 1234—and only those numbers—out of abc22 1,234.56 9.9.9.9 def 1234 is a wrong answer.

First of all, if you don't need to do this all in one regex, don't. A single regex for two different number formats is hard to maintain even when they aren't embedded in other text. What you should really do is split the whole thing on whitespace, then run two or three smaller regexes on the results. If that's not an option for you, keep reading.

Basic pattern

Considering the examples you've given, here's a simple regex that allows pretty much any integer or decimal in 0000 format and blocks everything else:

^\d*\.?\d+$

Here's one that requires 0,000 format:

^\d{1,3}(,\d{3})*(\.\d+)?$

Put them together, and commas become optional as long as they're consistent:

^(\d*\.?\d+|\d{1,3}(,\d{3})*(\.\d+)?)$ Embedded numbers

The patterns above require the entire input to be a number. You're looking for numbers embedded in text, so you have to loosen that part. On the other hand, you don't want it to see catch22 and think it's found the number 22. If you're using something with lookbehind support (like C#, .NET 4.0+), this is pretty easy: replace ^ with (? and $ with (?!\S) and you're good to go:

(?

If you're working with JavaScript or Ruby or something, things start looking more complex:

(?:^|\s)(\d*\.?\d+|\d{1,3}(?:,\d{3})*(?:\.\d+)?)(?!\S)

You'll have to use capture groups; I can't think of an alternative without lookbehind support. The numbers you want will be in Group 1 (assuming the whole match is Group 0).

Validation and more complex rules

I think that covers your question, so if that's all you need, stop reading now. If you want to get fancier, things turn very complex very quickly. Depending on your situation, you may want to block any or all of the following:

Empty input Leading zeroes (e.g. 000123) Trailing zeroes (e.g. 1.2340000) Decimals starting with the decimal point (e.g. .001 as opposed to 0.001)

Just for the hell of it, let's assume you want to block the first 3, but allow the last one. What should you do? I'll tell you what you should do, you should use a different regex for each rule and progressively narrow down your matches. But for the sake of the challenge, here's how you do it all in one giant pattern:

(?

And here's what it means:

(? (?:^|\s)(?=.)((?:0|(?:[1-9](?:\d*|\d{0,2}(?:,\d{3})*)))?(?:\.\d*[1-9])?)(?!\S)

The numbers you're looking for will be in capture group 1.

Tested here: http://rubular.com/r/3HCSkndzhT

One final note

Obviously, this is a massive, complicated, nigh-unreadable regex. I enjoyed the challenge, but you should consider whether you really want to use this in a production environment. Instead of trying to do everything in one step, you could do it in two: a regex to catch anything that might be a number, then another one to weed out whatever isn't a number. Or you could do some basic processing, then use your language's built-in number parsing functions. Your choice.

Some days ago, I worked on the problem of removing trailing zeros from the string of a number.

In the continuity of that problem, I find this one interesting because it widens the problem to numbers comprising commas.

I have taken the regex's pattern I had writen in that previous problem I worked on and I improved it in order that it can treat the numbers with commas as an answer for this problem.

I've been carried away with my enthusiasm and my liking of regexes. I don't know if the result fits exactly to the need expressed by Michael Prescott. I would be interested to know the points that are in excess or in lack in my regex, and to correct it to make it more suitable for you.

Now, after a long session of work on this regex, I have a sort of weight in the brain, so I'm not fresh enough to give a lot of explanation. If points are obscure, and if anybody may come to be interested enough, please, ask me.

The regex is built in order that it can detect the numbers expressed in scientific notation 2E10 or even 5,22,454.12E-00.0478 , removing unnecessary zeros in the two parts of such numbers too. If an exponent is equal to zero , the number is modified so that there is no more exponent.

I put some verification in the pattern so that some particular cases will not match, for exemple '12..57' won't match. But in ',111' the string '111' matches because the preceding comma is considered a comma not being in a number but a comma of sentence.

I think that the managing of commas should be improved, because it seems to me that there are only 2 digits between commas in Indian numbering. It won't be dificult to correct, I presume

Here after is a code demonstrating how my regex works. There are two functions, according if one wants the numbers '.1245' to be transformed in '0.1245' or not. I wouldn't be surprised if errors or unwanted matchings or unmatchings will remain for certain cases of number strings; then I'd like to know these cases to understand and correct the deficiency.

I apologize for this code written in Python, but regexes are trans-langage and I think everybody will be capable of undertsanding the reex's pattern

import re regx = re.compile('(?


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有